package cn.jnetty.utils;

import cn.jnetty.utils.timer.*;
import cn.jnetty.remoting.JnettyThreadFactory;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author 猪哥亮
 * @email 1030681978@qq.com
 * @date 2020/3/15 17:07
 * 描述：
 */
public class JnettyTimerUtil {

    private static final ExecutorService executor;
    private static final TimerModel model;

    static {
        executor = new ThreadPoolExecutor(1, 1, 0L
                , TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()
                , new JnettyThreadFactory("定时任务线程"));
        model = new TimerModel();
        model.setMonth(new ArrayList<>());
        model.setWeek(new ArrayList<>());
        model.setDay(new ArrayList<>());
        model.setHour(new ArrayList<>());
        model.setMinute(new ArrayList<>());
        model.setSecond(new ArrayList<>());
        model.setMillisecond(new ArrayList<>());
        model.setTimerMap(new HashMap<>());
    }
    public static void submit(JnettyTask runnable){
        executor.submit(() -> submit0(runnable));
    }
    public static void remove(JnettyTask runnable){
        executor.submit(() -> remove0(runnable));
    }
    public static void remove(String id){
        executor.submit(() -> remove1(id));
    }
    public static void execute(JnettyTask.MyTimerUtil timerUtil){
        switch (timerUtil){
            case DAY:
                executeDay();
                break;
            case HOUR:
                executeHour();
                break;
            case WEEK:
                executeWeek();
                break;
            case MONTH:
                executeMonth();
                break;
            case MINUTE:
                executeMinute();
                break;
            case SECOND:
                executeSecond();
                break;
            case MILLISECOND:
                executeMillisecond();
                break;
            default:
                break;
        }
    }
    private static void executeMonth(){
        executor(model.getMonth());
    }
    private static void executeDay(){
        executor(model.getDay());
    }
    private static void executeWeek(){
        executor(model.getWeek());
    }
    private static void executeHour(){
        executor(model.getHour());
    }
    private static void executeMinute(){
        executor(model.getMinute());
    }
    private static void executeSecond(){
        executor(model.getSecond());
    }
    private static void executeMillisecond(){
        executor(model.getMillisecond());
    }
    private static void executor(List<JnettyTask> list){
        executor.submit(() -> {
            Iterator<JnettyTask> iterator = list.iterator();
            while (iterator.hasNext()){
                JnettyTask next = iterator.next();
                next.timer();
                if(next.isDestroy()){
                    remove1(next.id());
                }
            }
        });
    }
    private static void submit0(JnettyTask runnable) {
        model.getTimerMap().put(runnable.id(),runnable);
        if (runnable instanceof Month) {
            model.getMonth().add(runnable);
        } else if (runnable instanceof Week) {
            model.getWeek().add(runnable);
        } else if (runnable instanceof Day) {
            model.getDay().add(runnable);
        } else if (runnable instanceof Hour) {
            model.getHour().add(runnable);
        } else if (runnable instanceof Minute) {
            model.getMinute().add(runnable);
        } else if (runnable instanceof Second) {
            model.getSecond().add(runnable);
        } else if (runnable instanceof Millisecond) {
            model.getMillisecond().add(runnable);
        }
    }

    private static JnettyTask remove0(JnettyTask runnable) {
        String id = null;
        for (JnettyTask value : model.getTimerMap().values()) {
            if(value.id().equals(runnable.id())){
                id = value.id();
            }
        }
        JnettyTask temp = null;
        if(id != null){
            temp =  model.getTimerMap().remove(id);
        }
        remove2(temp);
        return temp;
    }

    private static JnettyTask remove1(String id) {
        JnettyTask temp = model.getTimerMap().remove(id);
        if(temp != null){
            remove2(temp);
        }
        return temp;
    }
    private static void remove2(JnettyTask temp){
        if (temp instanceof Month) {
            model.getMonth().remove(temp);
        } else if (temp instanceof Week) {
            model.getWeek().remove(temp);
        } else if (temp instanceof Day) {
            model.getDay().remove(temp);
        } else if (temp instanceof Hour) {
            model.getHour().remove(temp);
        } else if (temp instanceof Minute) {
            model.getMinute().remove(temp);
        } else if (temp instanceof Second) {
            model.getSecond().remove(temp);
        } else if (temp instanceof Millisecond) {
            model.getMillisecond().remove(temp);
        }
    }
    private static class TimerModel {
        private Map<String, JnettyTask> timerMap;
        private List<JnettyTask> month;
        private List<JnettyTask> week;
        private List<JnettyTask> day;
        private List<JnettyTask> hour;
        private List<JnettyTask> minute;
        private List<JnettyTask> second;
        private List<JnettyTask> millisecond;

        public Map<String, JnettyTask> getTimerMap() {
            return timerMap;
        }

        public void setTimerMap(Map<String, JnettyTask> timerMap) {
            this.timerMap = timerMap;
        }

        public List<JnettyTask> getMonth() {
            return month;
        }

        public void setMonth(List<JnettyTask> month) {
            this.month = month;
        }

        public List<JnettyTask> getWeek() {
            return week;
        }

        public void setWeek(List<JnettyTask> week) {
            this.week = week;
        }

        public List<JnettyTask> getDay() {
            return day;
        }

        public void setDay(List<JnettyTask> day) {
            this.day = day;
        }

        public List<JnettyTask> getHour() {
            return hour;
        }

        public void setHour(List<JnettyTask> hour) {
            this.hour = hour;
        }

        public List<JnettyTask> getMinute() {
            return minute;
        }

        public void setMinute(List<JnettyTask> minute) {
            this.minute = minute;
        }

        public List<JnettyTask> getSecond() {
            return second;
        }

        public void setSecond(List<JnettyTask> second) {
            this.second = second;
        }

        public List<JnettyTask> getMillisecond() {
            return millisecond;
        }

        public void setMillisecond(List<JnettyTask> millisecond) {
            this.millisecond = millisecond;
        }
    }
}
